前面模組化歷史不小心鑽太深,在稍微有點長的前情提要後,今天終於要講回正題了。
在 Webpack 橫空出世後,將原本 JavaScript 模組化的概念利用 loader 擴充到 CSS、圖片等資源,並藉由其彈性化的設定與 plugin 來決定我們如何開發、打包,讓前端工程化這件事得以實現。因此當時許多前端框架的生態系也對齊採用 Webpack,像是早期的 create-react-app
、Vue CLI
,甚至到當前的 Next.js 穩定版仍是使用 Webpack。
但 Webpack 發展了十多年到現在,一直為人所詬病的不外乎幾點:
以下將針對這三個問題做展開,來聊聊現代網頁開發中,有哪些工具試圖解決這些問題。
先做個名詞定義,關於從網頁開發到打包部署過程中,你可能會看到 build tool、bundler、compiler 這些詞,我一開始也很難分清楚前兩者的不同。
Build tool 中文有人翻作構建工具,但我覺得還是蠻困惑的,因為其中有 build 這個字,是不是就代表跟 build code 有關?那跟 bundle 又有何不同?
直到我看到 Rsbuild 文件中的這張圖:
看起來 build tool 比較多指的是開發時用到的 dev server 這個功能,另外也跟 HMR (Hot Module Replacement) 這個特性比較有關。但在看了許多文件對自己的定義後,我覺得其實這些詞不同工具間也是有點混用,所以不用太糾結。
就像 Webpack 文件上稱自己為 bundler,但其實他後來也內建整合了 webpack-dev-server 這個 build tool 的功能;Rspack 又更亂了,雖然他有將其中的 build tool 部份稱為 Rsbuild 區分開來,但 Rsbuild 的文件中又提到它的特性不只有 dev server 的功能,然後跟其他工具的效能比較圖根本就是 Rspack/Rsbuild 都是同一張。
簡單整理的話,我覺得可以說是該工具代表性的品牌名 (Webpack、Vite、Rspack) 可以統稱為打包與開發工具,其中在各自生態系的整合中能做到 dev server 與 bundler 的功能,然後在開發或打包時會用上底層需要的 compiler (像是 Babel、SWC) 去做語法轉譯,細分的話可能會是這樣:
webpack-dev-server
做 build toolesbuild
、Rollup
做 bundlerRsbuild
webpack-dev-server
做客製化版的 build tool,打包時則是用 Webpack
當作 bundler另外其實我覺得這邊名詞定義不用太糾結的還有 compiler 與 transpiler。像是 Babel 與 SWC (Speedy Web Compiler) 都稱自己為 compiler。
但就 CS 定義上來說:
Compile 指的是將 source code 編譯成機器能讀懂的 machine code 等低階語言
Transpile 指的是將 source code 轉譯成另一種 source code,像是將 ES6 轉成 ES5、TypeScript 轉成 JavaScript
但可能也是因為名詞定義這種事有時候本來就參雜了一些主觀想法,所以不用太糾結。(ref)
針對第一點,分別有幾個工具嘗試簡化 Webpack 設定複雜的問題,但因為算是比較早期的工具,這邊不會細講,只簡單做一些簡介。
主要用來做為 ESM 的模組打包工具,設定上相對 Webpack 簡單許多
Vite 背後採用的 bundler
號稱 zero configuration 的打包工具
從 NPM trends 上看相比其他 bundler 下載數較少
有趣的是好奇看了它的原始碼發現其中有 Rust,於是找到了它的 roadmap,看起來其中一個目標有打算重寫為 Rust 來改善打包效率。
在 Webpack、Rollup、Parcel 這些工具中的 dev server 用的是 bundle-based 的模式,也就是每次你在開發儲存修改後,要在畫面上看到改變就一定需要經過一個完整的打包過程。
直到 ESM 的發展與普及後,開發者想到可以利用瀏覽器支援原生 ESM 的這個特性來提升 dev server 的開發體驗,因此有了 Native-ESM-based 的架構,從先驅 Snowpack 到現在廣為人知的 Vite。
關於上面的這個運作原理我還蠻有興趣深入理解的,但怕這邊寫太多會在後面章節中另外展開,這邊先做個簡介
算是 Vite 的啟迪者 (ref)。2022 年官方宣布不再維護的消息,建議可以改用 Vite 作為替代方案,而之後原開發團隊跑去開發 Astro,而 Astro 的 CLI 也是建立於 Vite 之上。
冷知識:Snowpack 的作者 Fred K. Schott 後來有寫了一篇關於他經營 Snowpack 開源專案的心得,以及如何將這些經驗帶到 Astro 的心路歷程 —— 《5 Things I Learned Building Snowpack to 20,000 Stars》
Vue 作者 Evan You 所開發,原本是想改善 Vue CLI 開發體驗不佳的問題,另外可能也是他做 Vue 開源做得有點累的 side project,現也成為 Solid、Qwik、Astro、Svelte 等現代前端框架的 dev server 基礎。其他內容後面講解 Vite 的運作原理時會再細談。
最後第三個在正式版打包速度過慢的問題,近代出現許多後起之秀,一改以往 JavaScript-based 的 bundler 的做法,改用效能更好的靜態語言,像是 Go-based 的 esbuild,還有此系列中會更有興趣關注的 Rust-based bundler,也因此這個系列才會命名為「Rust 的戰國時代」,後面會著重在這些工具的介紹,這邊先做個簡介。
另外還有幾套最近才知道但沒研究很深的 build tool,這裡也記錄一下:
今天稍微說明了下 build tool 與 bundler 的區別,並從 Webpack 的三個問題,帶出各款現代效能飛快的 build tool、bundler 的簡介,避免篇幅過長,細節會再後面繼續開展。明天也將會繼續聊聊 Vite 生態系的大小事。